package bancosys.tec.services.implementor;

import java.util.List;

import jmine.tec.di.metadata.DependencyMetaData;
import jmine.tec.di.scope.TypedScope;
import jmine.tec.di.type.TypeConvertionException;
import jmine.tec.services.api.ActionsEnum;
import jmine.tec.services.api.ServiceExecutionException;

import org.springframework.transaction.TransactionDefinition;

import bancosys.tec.services.implementor.descriptor.InstanceCreator;
import bancosys.tec.services.implementor.descriptor.ServiceExecutionProxy;
import bancosys.tec.services.implementor.descriptor.ServiceOutputExtractor;
import bancosys.tec.services.implementor.descriptor.ServiceValidator;

/**
 * Acessor para implementadores de servicos. Clientes da API de serviço só precisam se comunicar com esta interface
 * 
 * @author MarceloT
 */
public interface ServiceImplementorAccessor {

    /**
     * Cria uma nova instancia, injetando dependencias. Pode devolver <code>null</code> se algum parametro obrigatorio para a construcao da
     * instancia nao existir. Se algum parametro de metodo não existir, o objeto devolvido pode estar incompleto.
     * 
     * @param scope o escopo
     * @return Object
     * @throws TypeConvertionException e
     */
    Object createWithDependencies(TypedScope scope) throws TypeConvertionException;

    /**
     * Execuca o servico, resolvendo parametros para a execucao do servico e coloca os parametros de saida no escopo passado. Relanca a
     * excecao que foi lancada durante a execucao do servico.
     * 
     * @param service a classe que implementa o servico.
     * @param scope o escopo
     * @throws Exception excecao
     */
    void executeAndFillScope(Object service, TypedScope scope) throws Exception;

    /**
     * @return o nome do servico.
     */
    String getServiceName();

    /**
     * @return {@link ActionsEnum} o tipo da acao
     */
    ActionsEnum getActionType();

    /**
     * @return <code>true</code> se este servico é stateless - ou seja, suas instâncias podem ser reaproveitadas.
     */
    boolean isStateless();

    /**
     * Valida o estado estatico
     * 
     * @param scope {@link TypedScope}
     * @return {@link List} de {@link String}
     */
    List<String> validateStaticState(TypedScope scope);

    /**
     * Execuca os metodos de validacao
     * 
     * @param target o 'alvo'
     * @param scope o escopo
     * @throws ServiceExecutionException se houver uma excecao
     */
    void validateBeforeExecution(Object target, TypedScope scope) throws ServiceExecutionException;

    /**
     * Devolve a classe concreta que implementa o servico
     * 
     * @return {@link Class}
     */
    Class<?> getImplementorType();

    /**
     * Devolve todas as dependencias que este servico necessita para ser executado. Modificacoes na Lista devolvida não devem ser refletidas
     * nas informacoes do servico implementado
     * 
     * @return {@link List}
     */
    List<DependencyMetaData> getAllDependencies();

    /**
     * Retorna o extrator de informacoes de output do servico.
     * 
     * @return o extrator de informacoes de output do servico
     */
    ServiceOutputExtractor getOutputExtractor();

    /**
     * Obtém a definição de trasação que este serviço exige para rodar.
     * 
     * @return TransactionDefinition
     */
    TransactionDefinition getTransactionDefinition();

    /**
     * @return {@link ServiceExecutionProxy}
     */
    ServiceExecutionProxy getServiceExecutionProxy();

    /**
     * @return {@link ServiceOutputExtractor}
     */
    ServiceOutputExtractor getExtractor();

    /**
     * @return {@link ServiceValidator}
     */
    ServiceValidator getValidator();

    /**
     * @return {@link InstanceCreator}
     */
    InstanceCreator getCreator();

}
